package edu.colorado.cs.correll.cudroplet.shaperecognition;

import java.util.HashSet;
import java.util.Set;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.MultiPoint;
import processing.core.PApplet;

public class Subgraph {
	ShapeRecognition shapeRecognition;
	Set<Robot> subgraphSet;

	Robot max;

	public Subgraph(ShapeRecognition shapeRecognition, Set<Robot> subgraphSet,
			Leader leader) {
		this.shapeRecognition = shapeRecognition;
		this.subgraphSet = subgraphSet;

		max = getMax(subgraphSet);
		leader.setLeader(max.id);
	}

	public MultiPoint getMultiPoint() {
		Coordinate[] coordinates = new Coordinate[subgraphSet.size()];
		int i = 0;
		for (Robot robot : subgraphSet) {
			coordinates[i++] = robot.getCoordinate();
		}
		
		return shapeRecognition.geometryFactory.createMultiPoint(coordinates);
	}

	Robot getMax(Set<Robot> subgraph) {
		int maxId = PApplet.MIN_INT;
		Robot max = null;
		for (Robot robot : subgraph) {
			if (robot.id > maxId) {
				maxId = robot.id;
				max = robot;
			}
		}
		return max;
	}

	public AlphaShapeCollection getAlphaShapeCollection() {
		// the communication radius is the diameter of the circumcircle
		float circumcircle_diameter = shapeRecognition.simulation.swarm.robotSettings.comm_radius;
		Set<Circumcircle> allCircumcircles = new HashSet<Circumcircle>();

		for(Robot a: subgraphSet) {
			for(Robot b: shapeRecognition.simulation.swarm.neighbors[a.id]) {
				allCircumcircles.add(new Circumcircle(circumcircle_diameter, a, b));
			}
		}
		
		Set<Circumcircle> boundaryCircumcircles = new HashSet<Circumcircle>();
		for(Circumcircle circumcircle: allCircumcircles) {
			Coordinate center = circumcircle.getCenter();
			Set<Robot> setA = shapeRecognition.simulation.swarm.neighbors[circumcircle.a.id];
			Set<Robot> setB = shapeRecognition.simulation.swarm.neighbors[circumcircle.b.id];
			Set<Robot> setIntersection = new HashSet<Robot>(setA);
			setIntersection.retainAll(setB);
			boolean empty = true; 
			for(Robot d: setIntersection) {
				if(center.distance(d.getCoordinate()) < circumcircle_diameter/2) {
					empty = false;
					break;
				}
			}
			if(empty) {
				boundaryCircumcircles.add(circumcircle);
			}
		}
		
		return new AlphaShapeCollection(shapeRecognition, allCircumcircles, boundaryCircumcircles);
	}

	public Geometry getCenteredMultiPoint() {
		Coordinate centroid = getMultiPoint().getCentroid().getCoordinate();
		Coordinate[] coordinates = new Coordinate[subgraphSet.size()];
		int i = 0;
		for (Robot robot : subgraphSet) {
			Coordinate c = robot.getCoordinate();
			coordinates[i++] = new Coordinate(c.x - centroid.x, c.y - centroid.y);
		}
		return shapeRecognition.geometryFactory.createMultiPoint(coordinates);
	}
}
